package com.cy.sys.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.cy.common.annotation.SysLogAnnotation;
import com.cy.common.exception.ServiceException;
import com.cy.common.pojo.SysMenuList;
import com.cy.common.pojo.SysPage;
import com.cy.common.pojo.SysUserView;
import com.cy.common.util.ShiroUtil;
import com.cy.sys.dao.SysMenuDao;
import com.cy.sys.dao.SysUserDao;
import com.cy.sys.dao.SysUserRoleDao;
import com.cy.sys.pojo.SysUser;
import com.cy.sys.service.SysUserService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

/**
 * 此类负责处理所有用户模块的逻辑
 * @author private
 *
 */
@Service
@Transactional(timeout = 30)
public class SysUserServiceImpl implements SysUserService {
	@Autowired
	private SysUserDao sysUserDao;
	@Autowired
	private SysUserRoleDao sysUserRoleDao;
	@Autowired
	private SysMenuDao sysMenuDao;
	
	/** 负责查询到分页数据并进行封装 */
	@SysLogAnnotation(methodName = "查询用户")
	@RequiresPermissions("sys:user:view")
	@Override
	public SysPage<SysUserView> doFindPageObjects(String username, Integer pageCurrent, Integer pageSize) {
		//1.进行参数校验
		if(pageCurrent==null || pageCurrent<1)
			throw new IllegalArgumentException("请求页码无效!");
		if(pageSize==null || pageSize<1)
			throw new IllegalArgumentException("页面显示条数无效!");
		//2.进行分页计算
		Page<Object> page = PageHelper.startPage(pageCurrent,pageSize);
		//3.查询数据
		List<SysUserView> userView = sysUserDao.doFindPageObjects(username);
		if(userView==null)
			throw new ServiceException("未知错误,查询用户列表失败!");
		//4.返回结果
		return new SysPage<>(pageCurrent, (int)page.getTotal(), pageSize, page.getPages(), userView);
	}

	/** 负责修改用户状态 */
	@SysLogAnnotation(methodName = "修改状态")
	@RequiresPermissions("sys:user:valid")
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int doValidById(Integer id, Integer valid) {
		//1.进行参数校验
		if(id==null || id<1)
			throw new IllegalArgumentException("请选择正确的用户进行修改!");
		if(valid!=1 && valid!=0)
			throw new IllegalArgumentException("状态异常,请选择正确的状态");
		//2.修改用户状态
		int rows = sysUserDao.updateValid(id,valid,ShiroUtil.getUserName());
		//3.返回结果给调用方
		return rows;
	}

	/** 保存用户信息 */
	@SysLogAnnotation(methodName = "新增用户")
	@RequiresPermissions("sys:user:add")
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int doSaveObject(SysUser sysUser,Integer... roleIds) {
		//1.进行参数校验
		if(sysUser==null)
			throw new IllegalArgumentException("请填写用户信息");
		if(StringUtils.isEmpty(sysUser.getUsername()))
			throw new IllegalArgumentException("请填写用户名!");
		if(StringUtils.isEmpty(sysUser.getPassword()))
			throw new IllegalArgumentException("请填写密码!");
		if(sysUser.getDeptId()==null||sysUser.getDeptId()<1)
			throw new IllegalArgumentException("请选择部门信息!");
		if(roleIds==null||roleIds.length<1)
			throw new IllegalArgumentException("请选择至少一个角色!");
		int count = sysUserDao.selectUsernameCount(sysUser.getUsername());
		if(count>0)
			throw new ServiceException("此用户名已经被占用!");
		//定义盐值
		String salt = UUID.randomUUID().toString();
		//进行加密
		SimpleHash sh = new SimpleHash("MD5", sysUser.getPassword(), salt, 1);
		//返回加密后的内容
		String newPassword = sh.toHex();
		//注入加密的盐值
		sysUser.setSalt(salt);
		//注入加密后的新密码
		sysUser.setPassword(newPassword);
		//进行存储用户数据
		sysUser.setCreatedUser(ShiroUtil.getUserName());
		int rows= sysUserDao.insertObject(sysUser);
		//保存其对应的角色关系
		sysUserRoleDao.insertObjects(sysUser.getId(), roleIds);
		//返回结果给调用方
		return rows;
	}

	/** 查询用户信息进行回显 */
	@Override
	public Map<String,Object> doFindObjectById(Integer id) {
		//1.进行参数的校验
		if(id==null||id<1)
			throw new IllegalArgumentException("请先选择需要修改的用户!");
		//初始化map,将用户信息与对应的角色关系id进行封装回传
		Map<String, Object> map = new HashMap<>();
		SysUserView user = sysUserDao.selectObjectById(id);
		if(user==null)
			throw new ServiceException("要修改的用户可能已经不存在!");
		map.put("user", user);
		List<Integer> roleIds = sysUserRoleDao.selectRoleIdsByUserId(id);
		map.put("roleIds", roleIds);
		//回传结果
		return map;
	}

	/** 修改用户信息 */
	@RequiresPermissions("sys:user:update")
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int doUpdateObject(SysUser sysUser, Integer[] roleIds) {
		//1.进行参数校验
		if(sysUser==null)
			throw new IllegalArgumentException("请填写用户信息");
		if(StringUtils.isEmpty(sysUser.getUsername()))
			throw new IllegalArgumentException("请填写用户名!");
		if(sysUser.getDeptId()==null||sysUser.getDeptId()<1)
			throw new IllegalArgumentException("请选择部门信息!");
		if(roleIds==null||roleIds.length<1)
			throw new IllegalArgumentException("请选择至少一个角色!");
		//2.先修改用户信息
		sysUser.setModifiedUser(ShiroUtil.getUserName());
		int rows = sysUserDao.updateObject(sysUser);
		if(rows==0)
			throw new ServiceException("修改失败,此用户可能已经不存在!");
		//3.在修改对应的角色关系
		sysUserRoleDao.deleteObjectsByUserId(sysUser.getId());//先删除
		sysUserRoleDao.insertObjects(sysUser.getId(), roleIds);
		//4.返回结果
		return rows;
	}

	/** 修改用户密码 */
	@SysLogAnnotation(methodName = "修改密码")
	@RequiresPermissions("sys_pwd_edit")
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int doUpdatePassword(String pwd, String newPwd, String cfgPwd) {
		//1.进行参数的校验
		if(StringUtils.isEmpty(pwd) || StringUtils.isEmpty(newPwd) || StringUtils.isEmpty(cfgPwd))
			throw new IllegalArgumentException("请填写修改信息!");
		if(!newPwd.equals(cfgPwd))
			throw new IllegalArgumentException("两次新密码输入不相符!");
		//2.进行原密码校验
		//2.0获取当前登录的用户
		SysUser loginUser = ShiroUtil.getUser();
		SysUser selectUser = sysUserDao.fondUserByUserName(loginUser.getUsername());
		if(selectUser==null)
			throw new IllegalArgumentException("当前用户状态异常!");
		//2.1查询登录用户的信息并将原密码进行加密
		String salt = selectUser.getSalt();
		String oldPwd = new SimpleHash("MD5", pwd, salt, 1).toHex();
		//2.2与登录用户的原密码进行比较
		if(!selectUser.getPassword().equals(oldPwd))
			throw new IllegalArgumentException("原密码不正确!");
		//将新密码进行研制加密并修改到原密码和盐值处
		String newSalt = UUID.randomUUID().toString();
		String newPassword = new SimpleHash("MD5", newPwd, newSalt, 1).toHex();
		int rows = sysUserDao.updatePassword(newPassword,newSalt,selectUser.getId(),ShiroUtil.getUserName());
		if(rows==0)
			throw new ServiceException("当前用户状态异常!");
		return rows;
	}
	//select p.id,p.name,p.url,c.id cid,c.name cname,c.url curl 
	//from sys_menus p join sys_menus c 
	//on p.parentId = c.id 
	//WHERE p.id in ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) and p.parentId is null
	/** 获取指定id用户的菜单URL */
	@Override
	public List<SysMenuList> doGetMenusUrlByUserId(Integer id) {
		//1.先进行参数校验
		if(id==null||id<1)
			throw new IllegalArgumentException("服务出错,请稍后再试");
		//2.根据用户id获取对应的菜单id
		List<Integer> menuId = sysUserRoleDao.selectMenuIdByUserId(id);
		if(menuId==null||menuId.size()<1)
			throw new ServiceException("您没有任何操作权限");
		List<SysMenuList> menuList = sysMenuDao.selectMenuUrlList(menuId);
		if(menuList==null||menuList.size()<1)
			throw new IllegalArgumentException("服务出错,请稍后再试");
		return menuList;
	}

}
